package org.oa.ai.chatController;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.micrometer.common.util.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import okhttp3.ResponseBody;
import okhttp3.*;
import okio.BufferedSource;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.oa.ai.chatModel.ApifoxModel;
import org.oa.ai.chatModel.InputStreamMultipartFile;
import org.oa.ai.chatModel.OcrRequest;
import org.oa.ai.chatModel.SwModel;
import org.oa.ai.config.GwAssistant;
import org.oa.ai.constat.ApiConstants;
import org.oa.ai.feign.AIFeignService;
import org.oa.ai.model.ModelService;
import org.oa.ai.utils.HttpUtils;
import org.oa.ai.word.WordToHtmlUtil;
import org.oa.ai.word.WordUtils;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.*;
import java.math.BigInteger;
import java.util.*;

@RestController
@RequestMapping("/gw")
@CrossOrigin
public class GwControllerNew {

    @Autowired
    private ModelService modelService;

    @Autowired
    private AIFeignService aiFeignService;

    @Value("${fc.username}")
    private String username;

    @Value("${fc.password}")
    private String password;

    @Value("${fc.url}")
    private String url;

    public Object userToken;

    @Autowired
    private GwAssistant gwAssistant;

    @CrossOrigin
    @PostMapping("/auth/login")
    public JSONObject authLogin(@RequestBody Map<String, Object> map) {
        JSONObject result = new JSONObject();
        // 获取用户名和密码
        Object usernameObj = map.get("username");
        Object passwordObj = map.get("password");

        if (usernameObj == null || passwordObj == null) {
            return null; // 参数缺失直接返回
        }

        String username = usernameObj.toString();
        String password = passwordObj.toString();

        JSONObject loginObj = new JSONObject();
        loginObj.set("username", username);
        loginObj.set("password", password);

        // 第一次登录尝试
        JSONObject loginResult = login(loginObj);

        if (loginResult == null) {
            return null; // 登录接口异常或无返回
        }

        int code = loginResult.getInt("code");

        if (code == 500) {
            JSONObject userCreateObj = new JSONObject();
            userCreateObj.set("nickName", username);
            userCreateObj.set("username", username);
            userCreateObj.set("pwd", password); // 使用原始密码而非用户名作为密码

            // 查询用户是否存在
            JSONObject userInfo = getUserInfo(username);
            JSONObject data = userInfo != null ? userInfo.getJSONObject("data") : null;

            if (data == null) {
                // 用户不存在则新增
                JSONObject addResult = addUser(userCreateObj);
                if (addResult != null && addResult.getInt("code") == 200) {
                    // 新增成功后再次登录
                    JSONObject retryLogin = login(loginObj);
                    if (retryLogin != null && retryLogin.getJSONObject("data") != null) {
                        result.set("code",  addResult.getInt("code"));
                        result.set("msg", addResult.getStr("message"));
                        result.set("token",  retryLogin.getJSONObject("data").getStr("token"));
                        return result;
                    }
                } else {
                    result.set("code", addResult.getInt("code"));
                    result.set("msg", "请联系管理员！" + addResult.getStr("message"));
                    // 新增失败
                    return result;
                }
            } else {
                // 用户存在但登录失败，可能是密码错误
                result.set("code", 500);
                result.set("msg", "请联系管理员！账号或密码错误！");
                return null;
            }
        } else if (code == 200) {
            // 登录成功直接返回 token
            result.set("code",  loginResult.getInt("code"));
            result.set("msg", loginResult.getStr("message"));
            result.set("token",  loginResult.getJSONObject("data").getStr("token"));
            return result;
        }

        return null;
    }

    /**
     * 获取方寸用户token
     */
    public JSONObject login(JSONObject loginObj) {
        // 登录用户获取token
        try {
            String username = loginObj.getStr("username");
            String password = loginObj.getStr("password");
            return HttpUtils.login(url + ApiConstants.AUTH_LOGIN, username, password);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }



    /**
     * 使用方寸的接口调用大模型，以文写文
     *  action: 3：续写; 4：扩写(段落); 5：改写； 6：提炼； 9：扩写(提纲)
     *  请示1 公告2 函3 公报5 决定6 决议7 令类8 报告9 批复10 议案12 通告13 通报14 通知15
     */
    @CrossOrigin
    @PostMapping(value = "/docDraft", produces = "text/event-stream;charset=UTF-8")
    public SseEmitter docDraft(@RequestBody Map<String, Object> map) {
        // 获取 token 并移除
        String token = (String) map.remove("token");
        if (token == null) throw new IllegalArgumentException("Token is required");
        String jsonStr = JSONUtil.toJsonStr(map);
        return HttpUtils.streamPostJson(url + ApiConstants.DOC_DRAFT_V2, jsonStr, token);
    }

    /**
     * 使用方寸的接口调用大模型，优化改稿
     */
    @CrossOrigin
    @PostMapping(value = "/optimizeRewrite", produces = "text/event-stream;charset=UTF-8")
    public SseEmitter optimizeRewrite(@RequestBody Map<String, Object> map) {
        // 获取 token 并移除
        String token = (String) map.remove("token");
        if (token == null) throw new IllegalArgumentException("Token is required");
        String jsonStr = JSONUtil.toJsonStr(map);
        // 使用 HttpUtils 的 streamPostJson 方法处理流式请求
        return HttpUtils.streamPostJson(url + ApiConstants.OPTIMIZE_REWRITE, jsonStr, token);
    }

    /**
     * 使用方寸的接口调用大模型，纠正错别字等
     */
    @CrossOrigin
    @PostMapping(value = "/correction")
    public JSONObject correction(@RequestBody Map<String, Object> map) {
        try {
            // 获取 token 并移除
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");
            // 2. 处理 Markdown 格式
            String text = map.get("text").toString();
            map.put("text", formatMarkdown(text));
            String jsonStr = JSONUtil.toJsonStr(map);

            // 3. 使用 HttpUtils 发送 POST 请求
            return HttpUtils.postJson(url + ApiConstants.CORRECTION, jsonStr, token);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public String formatMarkdown(String input) {
        // 找到 <think> 和 </think> 的位置
        int startIndex = input.indexOf("<think>");
        int endIndex = input.indexOf("</think>") + "</think>".length();
        // 删除 <think> 标签及其内容
        String result;
        if (startIndex != -1 && endIndex != -1) {
            result = input.substring(0, startIndex) + input.substring(endIndex);
        } else {
            result = input; // 如果没有找到标签，返回原字符串
        }
        return result;
    }

    /**
     * 使用方寸的接口调用大模型，获取国标文件
     */
    @CrossOrigin
    @GetMapping(value = "/getStandardFile")
    public JSONObject getStandardFile(@RequestParam String token) {
        try {
            // 2. 使用 HttpUtils 发送 GET 请求
            return HttpUtils.get(url + ApiConstants.GET_STANDARD_FILE, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，通过文本识别要素
     */
    @CrossOrigin
    @PostMapping(value = "/identifyingFeature")
    public String identifyingFeature(@RequestBody Map<String, Object> map) {
        try {
            // 获取 token 并移除
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");
            // 2. 处理 Markdown 格式
            String text = map.get("content").toString();
            map.put("content", formatMarkdown(text));
            String jsonStr = JSONUtil.toJsonStr(map);

            // 3. 使用 HttpUtils 发送 POST 请求
            JSONObject response = HttpUtils.postJson(url + ApiConstants.IDENTIFYING_FEATURE, jsonStr, token);
            return response.toString();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 使用方寸的接口调用大模型，智能排版，直接返回文件id
     */
    @CrossOrigin
    @PostMapping(value = "/smartComposing")
    public String smartComposing(@RequestBody ApifoxModel bean) {
        try {
            String token = bean.getToken();
            bean.setToken("");
            // 2. 构建请求体
            JSONObject jsonObject = JSONUtil.parseObj(bean);
            jsonObject.remove("token");
            String jsonStr = JSONUtil.toJsonStr(jsonObject);

            // 使用 HttpUtils 获取文件流
            InputStream inputStream = HttpUtils.postFileStream(
                    url + ApiConstants.SMART_COMPOSING,
                    jsonStr,
                    token
            );
            // 加载 docx 文件
            XWPFDocument document = new XWPFDocument(OPCPackage.open(inputStream));
            // 存储书签名 -> 内容 的映射
            Map<String, StringBuilder> bookmarkContents = new HashMap<>();
            // 用于记录当前正在处理的书签栈（支持嵌套）
            Deque<CTBookmark> bookmarkStack = new LinkedList<>();
            // 遍历段落
            for (CTP paragraph : document.getDocument().getBody().getPList()) {
                // 检查是否有书签开始
                List<CTBookmark> starts = paragraph.getBookmarkStartList();
                if (starts != null) {
                    for (CTBookmark start : starts) {
                        String name = start.getName();
                        if (name != null && !name.isEmpty()) {
                            // 开始一个新的书签
                            bookmarkStack.push(start);
                            bookmarkContents.putIfAbsent(name, new StringBuilder());
                        }
                    }
                }
                // 检查是否有书签结束
                List<CTMarkupRange> ends = paragraph.getBookmarkEndList();
                Set<String> endedBookmarks = new HashSet<>(); // 已结束的书签
                if (ends != null && !ends.isEmpty()) {
                    for (CTMarkupRange end : ends) {
                        BigInteger id = end.getId();
                        // 找到匹配的书签起始点
                        for (Iterator<CTBookmark> it = bookmarkStack.iterator(); it.hasNext();) {
                            CTBookmark bookmark = it.next();
                            if (bookmark.getId() == id) {
                                endedBookmarks.add(bookmark.getName());
                                it.remove(); // 移除栈中已结束的书签
                                break;
                            }
                        }
                    }
                }
                // 收集文本：如果当前有打开的书签，则写入其内容
                if (!bookmarkStack.isEmpty()) {
                    StringBuilder segment = new StringBuilder(); // 用于拼接本段内容
                    for (CTR run : paragraph.getRList()) {
                        String text = null;
                        if (run.getTArray() != null && run.getTArray().length > 0) {
                            text = run.getTArray(0).getStringValue();
                        }
                        if (text != null && !text.isEmpty()) {
                            segment.append(text); // 保留原始文本中的空格
                        }
                    }
                    // 将整个段落的内容加上换行符，再追加到各个书签中
                    if (!segment.isEmpty()) {
                        String paragraphText = segment.toString() + "\n"; // 添加段落换行
                        for (CTBookmark bookmark : bookmarkStack) {
                            bookmarkContents.get(bookmark.getName()).append(paragraphText);
                        }
                    }
                }
            }
            // 处理未闭合的书签
            for (CTBookmark bookmark : bookmarkStack) {
                System.out.println("⚠️ 警告：书签 [" + bookmark.getName() + "] 未闭合");
                bookmarkContents.get(bookmark.getName());
            }
            String zhengwenContent = bookmarkContents.getOrDefault("{{zhengwen}}", new StringBuilder()).toString();
            return zhengwenContent;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InvalidFormatException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，篇章校对
     */
    @CrossOrigin
    @PostMapping(value = "/proofread")
    public JSONObject proofread(@RequestBody Map<String, Object> map) {
        try {
            // 1.获取 token 并移除
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");

            // 2. 构建请求体
            String jsonStr = JSONUtil.toJsonStr(map);

            // 3. 使用 HttpUtils 发送 POST 请求
            return HttpUtils.postJson(url + ApiConstants.PROOFREAD_ASYNC, jsonStr, token);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，查询篇幅校对结果
     */
    @CrossOrigin
    @PostMapping(value = "/queryProofreadResult")
    public JSONObject queryProofreadResult(@RequestBody Map<String, Object> map) {
        try {
            // 1.获取 token 并移除
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");

            // 2. 构建请求体
            String jsonStr = JSONUtil.toJsonStr(map);

            // 3. 使用 HttpUtils 发送 POST 请求
            return HttpUtils.postJson(url + ApiConstants.PROOFREAD_RESULT, jsonStr, token);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 调用方寸模型，上传本地附件
     */
    @CrossOrigin
    @PostMapping(value = "/uploadFile")
    public JSONObject uploadFile(@RequestParam("file") MultipartFile file, @RequestParam String token) {
        try {
            // 1.获取 token 并移除
            if (StringUtils.isEmpty(token)) throw new IllegalArgumentException("Token is required");
            // 2. 使用 HttpUtils 工具类发送文件上传请求
            return HttpUtils.uploadFile(url + ApiConstants.UPLOAD_FILE, file, token);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 调用方寸模型，上传本地附件，以文写文
     */

    @CrossOrigin
    @PostMapping(value = "/local/uploadFile")  // 设置返回给前端文本的编码
    public JSONObject localUploadFile(@RequestParam("file") MultipartFile file, @RequestParam String token){
        try {
            // 1.获取 token 并移除
            if (StringUtils.isEmpty(token)) throw new IllegalArgumentException("Token is required");
            // 2. 使用 HttpUtils 工具类发送文件上传请求
            return HttpUtils.uploadFile(url + ApiConstants.LOCAL_UPLOAD_FILE, file, token);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 调用方寸模型，OCR识别：通过文件上传识别文件内容
     */
    @CrossOrigin
    @PostMapping(value = "/ocr/uploadFile")  // 设置返回给前端文本的编码
    public JSONObject ocrUploadFile(@RequestParam("file") MultipartFile file, @RequestParam String token){
        try {
            // 1.获取 token 并移除
            if (StringUtils.isEmpty(token)) throw new IllegalArgumentException("Token is required");
            // 2. 使用 HttpUtils 工具类发送文件上传请求
            return HttpUtils.uploadFile(url + ApiConstants.OCR_UPLOAD_FILE, file, token);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 调用方寸模型，OCR识别：通过文件图片id进行获取图片
     */
    @CrossOrigin
    @GetMapping(value = "/getOcrImg/{id}")
    public void getOcrImg(@PathVariable("id") String id, HttpServletResponse response, @RequestParam String token) {
        try {
            // 1.获取token
            if (StringUtils.isNotEmpty(token)) {
                // 2. 使用 HttpUtils 工具类下载图片并输出到响应流
                String imageUrl = url + ApiConstants.OCR_PREVIEW + id;
                HttpUtils.downloadFileToResponse(imageUrl, token, response);
            }

        } catch (IOException e) {
            try {
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to retrieve image");
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
            throw new RuntimeException(e);
        }
    }


    /**
     * 通过正文id获取正文内容，通过正文内容进行提炼数据
     * @return
     */
    @CrossOrigin
    @PostMapping(value = "/extractData/{zw}", produces = "text/event-stream;charset=UTF-8")
    public SseEmitter extractData(@PathVariable("zw") String zw, @RequestBody Map<String, Object> map) {
        // 1.获取 token 并移除
        String token = (String) map.remove("token");
        if (token == null) throw new IllegalArgumentException("Token is required");

        // 先获取正文内容
        String zwContent = aiFeignService.getFileContent(zw);
        map.put("prompt", zwContent);
        map.put("action", 6);

        String jsonStr = JSONUtil.toJsonStr(map);
        String fullUrl = url + ApiConstants.DOC_DRAFT_V2;

        return HttpUtils.streamPostJson(fullUrl, jsonStr, token);
    }


    /**
     * 使用方寸的接口调用大模型，查询政策工文库数量
     */
    @CrossOrigin
    @PostMapping(value = "/getRetrievalDataSum")  // 设置返回给前端文本的编码
    public JSONObject getRetrievalDataSum(@RequestBody Map<String, Object> map){
        try {
            // 1.获取 token 并移除
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");

            // 2. 构建请求体
            String jsonStr = JSONUtil.toJsonStr(map);

            // 3. 使用 HttpUtils 发送 POST 请求
            return HttpUtils.postJson(url + ApiConstants.RETRIEVAL_DATA_SUM, "", token);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，查询用户本地工文库
     */
    @CrossOrigin
    @PostMapping(value = "/userRepository")  // 设置返回给前端文本的编码
    public JSONObject getLoaclLib(@RequestBody Map<String, Object> map){
        try {
            // 1.获取token
            Object token = map.get("token");
            if (token == null) {
                return null;
            }
            // 3. 使用 HttpUtils 发送 POST 请求
            return HttpUtils.postJson(url + ApiConstants.USER_REPOSITORY, "{}", token.toString());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 使用方寸的接口调用大模型，地区分类查询
     */
    @CrossOrigin
    @PostMapping("/getCityRegion")
    public JSONObject getCityRegion(@RequestBody Map<String, Object> map) throws IOException {
        try {
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");
            // 3. 使用 HttpUtils 发送 POST 请求
            return HttpUtils.postJson(url + ApiConstants.CITY_REGION, "{}", token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 使用方寸的接口调用大模型，获取检索文章类型
     */
    @CrossOrigin
    @GetMapping(value = "/getConditionType/{code}")  // 设置返回给前端文本的编码
    public JSONObject getCondition(@PathVariable("code") Integer code, @RequestParam String token){
        try {
            if (token == null) throw new IllegalArgumentException("Token is required");

            return HttpUtils.get(url + ApiConstants.CONDITION_TYPE + "?code=" + code, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 使用方寸的接口调用大模型，查询最新入库文件
     */
    @CrossOrigin
    @GetMapping(value = "/getRecent")  // 设置返回给前端文本的编码
    public JSONObject getRecent(@RequestParam String token){
        try {
            if (token == null) throw new IllegalArgumentException("Token is required");
            return HttpUtils.get(url + ApiConstants.GET_RECENT + "?searchFlag=1&size=20", token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，查询我的收藏
     */
    @CrossOrigin
    @GetMapping(value = "/getMyFavorite")  // 设置返回给前端文本的编码
    public JSONObject getMyFavorite(@RequestParam String token){
        try {
            if (token == null) throw new IllegalArgumentException("Token is required");
            return HttpUtils.get(url + ApiConstants.GET_MY_FAVORITE + "?page=1&size=1000000", token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，通过条件智能检索
     */
    @CrossOrigin
    @PostMapping(value = "/retrieval")  // 设置返回给前端文本的编码
    public JSONObject retrieval(@RequestBody Map<String, Object> map){
        try {
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");

            String jsonStr = JSONUtil.toJsonStr(map);
            return HttpUtils.postJson(url + ApiConstants.RETRIEVAL_V2, jsonStr, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，获取公文详情
     */
    @CrossOrigin
    @GetMapping(value = "/getDetail/{sourceId}")  // 设置返回给前端文本的编码
    public JSONObject getDetail(@PathVariable("sourceId") String sourceId, @RequestParam String token){
        try {
            return HttpUtils.get(url + ApiConstants.GET_DETAIL + "?sourceId=" + sourceId, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，获取公文目录结构
     */
    @CrossOrigin
    @GetMapping(value = "/getOutline/{sourceId}")  // 设置返回给前端文本的编码
    public JSONObject getOutline(@PathVariable("sourceId") String sourceId, @RequestParam String token){
        try {
            return HttpUtils.get(url + ApiConstants.GET_OUTLINE + "?sourceId=" + sourceId, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，获取关键句摘录
     */
    @CrossOrigin
    @GetMapping(value = "/getPunchline/{sourceId}")  // 设置返回给前端文本的编码
    public JSONObject getPunchline(@PathVariable("sourceId") String sourceId, @RequestParam String token){
        try {
            return HttpUtils.get(url + ApiConstants.GET_PUNCHLINE + "?sourceId=" + sourceId, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，内容摘要
     */
    @CrossOrigin
    @PostMapping("/getRightAssistRead")
    public JSONObject getRightAssistRead(@RequestBody Map<String, Object> map) throws IOException {
        try {
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");
            String jsonStr = JSONUtil.toJsonStr(map);
            return HttpUtils.postJson(url + ApiConstants.GET_RIGHT_ASSIST_READ, jsonStr, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 使用方寸的接口调用大模型，加入收藏
     */
    @CrossOrigin
    @PostMapping(value = "/addCollection")  // 设置返回给前端文本的编码
    public JSONObject addCollection(@RequestBody Map<String, Object> map){
        try {
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");
            String jsonStr = JSONUtil.toJsonStr(map);
            return HttpUtils.postJson(url + ApiConstants.ADD_COLLECTION, jsonStr, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 使用方寸的接口调用大模型，加入收藏
     */
    @CrossOrigin
    @PostMapping(value = "/delCollection")  // 设置返回给前端文本的编码
    public JSONObject delCollection(@RequestBody Map<String, Object> map){
        try {
            String token = (String) map.remove("token");
            if (token == null) throw new IllegalArgumentException("Token is required");
            String jsonStr = JSONUtil.toJsonStr(map);
            return HttpUtils.postJson(url + ApiConstants.DEL_COLLECTION, jsonStr, token);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 将用户数据同步到方寸模型中
     */
    @CrossOrigin
    @GetMapping(value = "/addAllUser/{id}")  // 设置返回给前端文本的编码
    public JSONObject addAllUser(@PathVariable("id") String userId){
        // 1.获取要新增的用户
        JSONArray jsonArray = aiFeignService.getAllUsers(userId);

        // 2.判断当前是否登录
//        if (userToken == null) {
//            setToken();
//        }

        JSONArray addSuccess = new JSONArray();  // 新增成功用户
        JSONArray addError = new JSONArray();   // 新增失败用户

        // 遍历新增
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);

            JSONObject object = new JSONObject();
            object.set("nickName", jsonObject.getStr("name"));
            object.set("username", "sr" + jsonObject.getStr("login_name"));
            object.set("pwd", "sr" + jsonObject.getStr("login_name"));

            // 3.查询用户是否存在
            JSONObject userInfo = getUserInfo(object.getStr("username"));
            JSONObject data = userInfo.getJSONObject("data");

            // 4.如果用户存在则修改用户信息
            if (data == null) {
                JSONObject result = addUser(object);
                System.out.println(result);
                if (result.getInt("code") == 200) {
                    addSuccess.add(object);
                }else {
                    addError.add(object);
                }
            }
        }

        // 构建返回数据
        JSONObject result = new JSONObject();
        result.set("addSuccess", addSuccess);
        result.set("addError", addError);
        result.set("successNum", addSuccess.size());
        result.set("errNum", addError.size());
        result.set("totalNum", jsonArray.size());

        return result;
    }

    /**
     * 查询用户
     */
    public JSONObject getUserInfo(String username) {
      try {
          if (userToken == null) {
              setToken(); // 如果 userToken 为空则重新登录获取
          }
          return HttpUtils.get(url + ApiConstants.FIND_USER_BY_USERNAME + "?username=" + username, userToken.toString());
      } catch (IOException e) {
          throw new RuntimeException(e);
      }
    }

    /**
     * 新增用户数据
     */
    public JSONObject addUser(JSONObject jsonObject){
        try {
            // 先获取token
            setToken();
            String jsonStr = JSONUtil.toJsonStr(jsonObject);
            return HttpUtils.postJson(url + ApiConstants.SIMPLE_ADD_USER, jsonStr, userToken.toString());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 修改用户数据
     */
    public JSONObject updateUser(JSONObject jsonObject){
        // 先获取token
        setToken();
        try {
            // 先获取token
            setToken();
            String jsonStr = JSONUtil.toJsonStr(jsonObject);
            return HttpUtils.postJson(url + ApiConstants.SIMPLE_ADD_USER, jsonStr, userToken.toString());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取方寸用户token
     */
    public void setToken() {
        // 登录用户获取token
        try {
            JSONObject result = HttpUtils.login(url + ApiConstants.AUTH_LOGIN, username, password);
            if (result.containsKey("data")) {
                userToken = result.getJSONObject("data").get("token");
            } else {
                throw new IOException("Failed to get token from response");
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 带着存储使用流式方式返回数据并区分用户隔离
     */
    @CrossOrigin
    @PostMapping("/sendMessage")  // 设置返回给前端文本的编码
    public SwModel assistantUniqueStream(@RequestBody OcrRequest ocrRequest) {
        SwModel stream = gwAssistant.stream(ocrRequest.getUserId(), ocrRequest.getMessage());
        return stream;
    }

    /**
     * 上传word文件，获取文件中的内容
     */
    @PostMapping("/importFile")
    public Map<String, Object> importFile(@RequestParam("file") MultipartFile file) throws Exception {
        Map<String, Object> response = new HashMap<>();
        boolean isDoc =  file.getOriginalFilename().endsWith(".doc");
        String html = WordToHtmlUtil.convertWordToHtml(file.getInputStream(), isDoc);
//        String html = WordUtils.convertWordToHtmlString(file);
        response.put("html", html);
        return response;
    }

    /**
     * 将html内容导出为docx文档
     */
    @PostMapping("/exportFile")
    public byte[] exportFile(@RequestBody Map<String, String> obj) throws Exception {
        try {
            String html = obj.get("htmlBody");
            // 创建内存输出流
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            // 使用 Aspose.Words 将 HTML 插入 Word 并写入输出流
            WordUtils.HtmlToWord(html, outputStream);
            // 返回响应
            byte[] byteArray = outputStream.toByteArray();
            return byteArray;

        } catch (Exception e) {
            throw new IOException("导出Word失败: " + e.getMessage());
        }
    }

    /**
     * 获取正文内容
     */
    @CrossOrigin
    @GetMapping(value = "/getZwContent/{zwid}")
    public String getZwContent(@PathVariable("zwid") String zwid) throws Exception {
//        // 使用正则表达式删除第一个非空白字符前的所有空格和换行符
//        if (fileContent != null && !fileContent.isEmpty()) {
//            fileContent = fileContent.replaceFirst("^\\s+", "");
//        }
//        return fileContent;
        File file = aiFeignService.getFileByGwid(zwid);

        return "";

    }


    public void test01 () throws IOException, InvalidFormatException {
        // 加载 docx 文件
        File file = new File("D:\\桌面\\b.docx");
        FileInputStream fis = new FileInputStream(file);
        XWPFDocument document = new XWPFDocument(OPCPackage.open(fis));

        // 存储书签名 -> 内容 的映射
        Map<String, StringBuilder> bookmarkContents = new HashMap<>();

        // 用于记录当前正在处理的书签栈（支持嵌套）
        Deque<CTBookmark> bookmarkStack = new LinkedList<>();

        // 遍历段落
        for (CTP paragraph : document.getDocument().getBody().getPList()) {

            // 检查是否有书签开始
            List<CTBookmark> starts = paragraph.getBookmarkStartList();
            if (starts != null) {
                for (CTBookmark start : starts) {
                    String name = start.getName();
                    if (name != null && !name.isEmpty()) {
                        // 开始一个新的书签
                        bookmarkStack.push(start);
                        bookmarkContents.putIfAbsent(name, new StringBuilder());
                    }
                }
            }

            // 检查是否有书签结束
            List<CTMarkupRange> ends = paragraph.getBookmarkEndList();
            Set<String> endedBookmarks = new HashSet<>(); // 已结束的书签
            if (ends != null && !ends.isEmpty()) {
                for (CTMarkupRange end : ends) {
                    BigInteger id = end.getId();
                    // 找到匹配的书签起始点
                    for (Iterator<CTBookmark> it = bookmarkStack.iterator(); it.hasNext();) {
                        CTBookmark bookmark = it.next();
                        if (bookmark.getId() == id) {
                            endedBookmarks.add(bookmark.getName());
                            it.remove(); // 移除栈中已结束的书签
                            break;
                        }
                    }
                }
            }

            // 收集文本：如果当前有打开的书签，则写入其内容
            if (!bookmarkStack.isEmpty()) {
                StringBuilder segment = new StringBuilder(); // 用于拼接本段内容

                for (CTR run : paragraph.getRList()) {
                    String text = null;
                    if (run.getTArray() != null && run.getTArray().length > 0) {
                        text = run.getTArray(0).getStringValue();
                    }
                    if (text != null && !text.isEmpty()) {
                        segment.append(text); // 保留原始文本中的空格
                    }
                }

                // 将整个段落的内容加上换行符，再追加到各个书签中
                if (!segment.isEmpty()) {
                    String paragraphText = segment.toString() + "\n"; // 添加段落换行
                    for (CTBookmark bookmark : bookmarkStack) {
                        bookmarkContents.get(bookmark.getName()).append(paragraphText);
                    }
                }
            }
        }

        // 处理未闭合的书签
        for (CTBookmark bookmark : bookmarkStack) {
            System.out.println("⚠️ 警告：书签 [" + bookmark.getName() + "] 未闭合");
            bookmarkContents.get(bookmark.getName()).append("（书签未闭合，内容可能不完整）");
        }

        // 输出结果
        for (Map.Entry<String, StringBuilder> entry : bookmarkContents.entrySet()) {
            System.out.println("书签名称: " + entry.getKey());
            System.out.println("书签内容: ");
            System.out.println(entry.getValue().toString());
            System.out.println("-----------------------------");
        }
        String zhengwenContent = bookmarkContents.getOrDefault("zhengwen", new StringBuilder()).toString();
//        return zhengwenContent;
    }

}
